#include "stdafx.h"
#include "net/SocketNotifier.hpp"

NET_NAMESPACE_BEGIN

CSocketNotifier::CSocketNotifier(const CSocket& socket) : m_socket(socket)
{
}

CSocketNotifier::~CSocketNotifier()
{
}

void CSocketNotifier::addObserver(CSocketReactor* pReactor, const CAbstractObserver& observer)
{
	m_nc.addObserver(observer);
	if (observer.accepts(pReactor->m_pReadableNotification))
		m_events.insert(pReactor->m_pReadableNotification.get());
	else if (observer.accepts(pReactor->m_pWritableNotification))
		m_events.insert(pReactor->m_pWritableNotification.get());
	else if (observer.accepts(pReactor->m_pErrorNotification))
		m_events.insert(pReactor->m_pErrorNotification.get());
	else if (observer.accepts(pReactor->m_pTimeoutNotification))
		m_events.insert(pReactor->m_pTimeoutNotification.get());
}

void CSocketNotifier::removeObserver(CSocketReactor* pReactor, const CAbstractObserver& observer)
{
	m_nc.removeObserver(observer);
	EventSet::iterator it = m_events.end();
	if (observer.accepts(pReactor->m_pReadableNotification))
		it = m_events.find(pReactor->m_pReadableNotification.get());
	else if (observer.accepts(pReactor->m_pWritableNotification))
		it = m_events.find(pReactor->m_pWritableNotification.get());
	else if (observer.accepts(pReactor->m_pErrorNotification))
		it = m_events.find(pReactor->m_pErrorNotification.get());
	else if (observer.accepts(pReactor->m_pTimeoutNotification))
		it = m_events.find(pReactor->m_pTimeoutNotification.get());
	if (it != m_events.end())
		m_events.erase(it);
}

bool CSocketNotifier::accepts(CSocketNotification* pNotification)
{
	return m_events.find(pNotification) != m_events.end();
}

bool CSocketNotifier::hasObserver(const CAbstractObserver& observer) const
{
	return m_nc.hasObserver(observer);
}

bool CSocketNotifier::hasObservers() const
{
	return m_nc.hasObservers();
}

std::size_t CSocketNotifier::countObservers() const
{
	return m_nc.countObservers();
}

static CSocket nullSocket;

void CSocketNotifier::dispatch(CSocketNotification* pNotification)
{
	pNotification->setSocket(m_socket);
	pNotification->add();
	try
	{
		m_nc.postNotification(pNotification);
	}
	catch (...)
	{
		pNotification->setSocket(nullSocket);
		throw;
	}
	pNotification->setSocket(nullSocket);
}


NET_NAMESPACE_END
